home *** CD-ROM | disk | FTP | other *** search
/ Suzy B Software 2 / Suzy B Software CD-ROM 2 (1994).iso / new_file / mintprgs / mint112s / mint112s.lzh / syscall.spp < prev    next >
Encoding:
Text File  |  1994-11-14  |  14.6 KB  |  526 lines

  1. ; Copyright 1992 Eric R. Smith
  2. ; Copyright 1992,1993,1994 Atari Corporation
  3. ; All rights reserved.
  4.  
  5. %include "magic.i"
  6. ;
  7. ; syscall: interface for system calls. The following entry points are
  8. ;    defined:
  9. ; _mint_bios:  entry point for the BIOS calls (trap #13)
  10. ; _mint_xbios: entry point for XBIOS calls (trap #14)
  11. ; _mint_dos:   entry point for GEMDOS calls (trap #1)
  12. ; _sig_return: user signal handlers return to this routine (see signal.c)
  13. ;              it is responsible for restoring the kernel's old context
  14. ;              via the Psigreturn() system call
  15. ; _lineA0:     calls the line A initialize routine
  16. ; _call_aes:   calls the GEM AES
  17. ; _call_dosound: calls the XBIOS Dosound() function
  18. ; _do_usrcall: calls a user supplied function (e.g. for Supexec), with
  19. ;           arguments supplied from global variables usrarg1, usrarg2, etc.
  20. ; _callout:    calls an external function, after first saving all registers,
  21. ;              and restores the registers afterward
  22. ;
  23. ; external variables referenced:
  24. ; _bios_tab, _bios_max:
  25. ;    table of entry points for BIOS routines, max # of routine
  26. ; _xbios_tab, _xbios_max:
  27. ;    ditto for XBIOS
  28. ; _dos_tab, _dos_max:
  29. ;    ditto for GEMDOS
  30. ; _curproc:
  31. ;    pointer to current process table entry, and hence to save area for
  32. ;    context (this is always the first entry in the PROC table).
  33. ;
  34. ; _bconbuf, _bconbsiz, _bconbdev:
  35. ;    256 byte buffer for Bconout() output. If _bconbsiz is non-zero,
  36. ;    there are that many bytes in _bconbuf waiting to be flushed. The
  37. ;    output is for device _bconbdev.
  38. ;
  39. ; The C function enter_kernel() is called on entry to the kernel, and the
  40. ; function leave_kernel() is called on exit. These functions are responsible
  41. ; for saving and restoring the various trap vectors, so that MiNT can trap
  42. ; out to TOS directly, but programs can only trap to MiNT.
  43. ;
  44. ; we also call certain BIOS functions directly if these are known not to
  45. ; require saving/restoring of context
  46. ;
  47.     TEXT
  48.     
  49.     XDEF    _mint_bios,_mint_xbios
  50.     XDEF    _mint_dos
  51.     XDEF    _pc_valid_return
  52.     XREF    _build_context
  53.     XREF    _restore_context
  54.     XREF    _proc_clock        ; controls process' allocation of CPU time
  55.     XREF    _enter_kernel
  56.     XREF    _leave_kernel
  57.     XREF    _preempt
  58.     XREF    _unwound_stack
  59.  
  60.     XREF    _check_sigs
  61.  
  62.     XREF    _curproc
  63.     XREF    _bios_tab,_bios_max
  64.     XREF    _xbios_tab,_xbios_max,_old_xbios
  65.     XREF    _dos_tab,_dos_max
  66.  
  67.     XREF    _bconbuf,_bconbsiz,_bconbdev
  68.     XREF    _bflush
  69.  
  70.     XREF    _ubconstat,_do_bconin,_ubcostat,_kbshift
  71.     
  72. _mint_dos:
  73.     clr.w    -(sp)            ; no frame format needed
  74. ; NOTE: FOR NOW, WE PRESERVE A0 ACROSS GEMDOS CALLS. THIS WILL CHANGE
  75. ; SOMEDAY, DON'T RELY ON IT!!!
  76.     move.l    _curproc,d0        ; note: preserve all regs but d0
  77.     addq.l    #4,d0            ; for compatibility
  78.  
  79.     move.l    d0,-(sp)        ; push pointer to syscall context save
  80.     jsr    _build_context
  81.     lea    _dos_tab,a5        ; set syscall_tab
  82.     move.w    _dos_max,d5        ; set syscall_max
  83. ;
  84. ; copy parameters onto process stack. a0 and a1 were set by _build_context
  85. ;
  86.  
  87.     move.l    _curproc,a0
  88.     move.l    (a0),sp            ; this puts us in our private stack
  89.     move.l    24(a1),-(sp)        ; a1 was set by build_context
  90.     move.l    20(a1),-(sp)
  91.     move.l    16(a1),-(sp)
  92.     move.l    12(a1),-(sp)
  93.     move.l    8(a1),-(sp)
  94.     move.l    4(a1),-(sp)
  95.     move.l    (a1),-(sp)
  96.     move.w    #1,-(sp)        ; flag for in GEMDOS
  97.     jsr    _enter_kernel        ; set up vectors appropriately
  98.     addq.w    #2,sp
  99.     bra    _syscall
  100.  
  101. _mint_xbios:
  102. ;
  103. ; Kludge for Setscreen: under Falcon TOS, this
  104. ; calls a GEMDOS function (Srealloc) and so
  105. ; we must *not* change any of the vectors!!
  106.  
  107.     btst    #5,(sp)            ; test for user/super mode
  108.     beq.s    LX_usr
  109. %ifdef ONLY030
  110.     lea    8(sp),a1
  111. %else
  112.     lea    6(sp),a1        ; supervisor mode: args on stack
  113.     tst.w    ($59e).w        ; test longframe
  114.     beq.s    LX_check
  115.     addq.w    #2,a1            ; stack is a bit bigger
  116. %endif
  117.     bra.s    LX_check
  118. LX_usr:
  119.     move.l    usp,a1            ; user mode: args on user stack
  120. LX_check:
  121.     cmp.w    #5,(a1)            ; check for Setscreen command
  122.     beq.s    LX_screen        ; no -- fall through
  123.  
  124.     clr.w    -(sp)            ; no frame format needed
  125.     move.l    _curproc,a0
  126.     pea    4(a0)            ; push pointer to syscall context save
  127.     jsr    _build_context
  128.     lea    _xbios_tab,a5        ; set syscall_tab
  129.     move.w    _xbios_max,d5        ; set syscall_max
  130. ;
  131. ; copy parameters onto process stack. a0 and a1 were set by _build_context
  132. ;
  133.  
  134.     move.l    _curproc,a0
  135.     move.l    (a0),sp            ; this puts us in our private stack
  136.     move.l    24(a1),-(sp)        ; a1 was set by build_context
  137.     move.l    20(a1),-(sp)
  138.     move.l    16(a1),-(sp)
  139.     move.l    12(a1),-(sp)
  140.     move.l    8(a1),-(sp)
  141.     move.l    4(a1),-(sp)
  142.     move.l    (a1),-(sp)
  143. %ifdef ONLY030
  144.     clr.w    -(sp)            ; flag: NOT GEMDOS
  145. %else
  146.     move.w    #0,-(sp)        ; flag: NOT GEMDOS
  147. %endif
  148.     jsr    _enter_kernel        ; set up vectors appropriately
  149.     addq.w    #2,sp
  150.     bra    _syscall
  151. ;
  152. ; For setscreen, jump directly to the ROM vector --
  153. ; this avoids all hazards (like changing the vectors)
  154.  
  155. LX_screen:
  156.     move.l    _old_xbios+8,a0
  157.     jmp    (a0)
  158.  
  159.  
  160. _mint_bios:
  161. ;
  162. ; Entering the kernel can be very expensive; so, we take a short-cut
  163. ; if possible -- we try some BIOS functions out, and if they
  164. ; succeed without blocking then we're done; otherwise, we go
  165. ; through the long procedure for entering the kernel
  166. ;
  167. ; These shortcuts aren't done when we're called in supervisor mode,
  168. ; because TOS uses very tiny stacks (smaller than we want); the
  169. ; shortcuts operate on the user-supplied ssp, whereas the "full"
  170. ; BIOS code works on our (private) system stack
  171. ;
  172. ; the shortcuts are also turned off if BIOSBUF=n
  173. ;
  174. %ifdef ONLY030
  175.     clr.w    -(sp)            ; flag: NOT a GEMDOS call
  176. %else
  177.     move.w    #0,-(sp)        ; flag: NOT a GEMDOS call
  178. %endif
  179.     jsr    _enter_kernel        ; set up BIOS vectors
  180.     addq.w    #2,sp
  181.     tst.w    _bconbdev        ; is BIOS buffering on?
  182.     bmi    L_bios            ; no; skip all this
  183.  
  184.     btst    #5,(sp)            ; test for user/super mode
  185.     bne.s    L_bios            ; if super, goto L_bios
  186.     tst.w    _proc_clock        ; are we about to be preempted?
  187.     beq.s    L_bios
  188.  
  189.     move.l    usp,a1            ; user mode: args on user stack
  190. L_ubios:
  191.     move.w    (a1),d0            ; get command
  192.     cmp.w    #3,d0            ; Bconout?
  193.     beq    do_bconout        ; yes -- go do it
  194. ;
  195. ; most of the remaining functions require BIOS vectors to be properly
  196. ; set up
  197.     tst.w    _bconbsiz        ; is BIOS output waiting?
  198.     bne.s    L_bios            ; yes -- do regular code
  199.  
  200. ; test for various BIOS functions
  201.     cmp.w    #1,d0            ; Bconstat?
  202.     bne.s    L_00
  203.     move.w    2(a1),-(sp)        ; push arg
  204.     jsr    _ubconstat
  205. L_1out:
  206.     addq.l    #2,sp
  207. L_0out:
  208.     move.l    d0,-(sp)        ; save d0
  209.     ori.w    #$0700,sr        ; spl7()
  210.     jsr    _leave_kernel
  211.     move.l    (sp)+,d0        ; retrieve value to be returned
  212.     rte                ; return to user
  213. L_00:
  214.     cmp.w    #2,d0            ; Bconin?
  215.     bne.s    L_01
  216.     move.w    2(a1),-(sp)        ; yes; push argument
  217.     jsr    _do_bconin
  218.     addq.w    #2,sp
  219.     cmp.w    #$dead,d0        ; would Bconin block?
  220.     bne.s    L_0out            ; no -- we're done
  221.     bra.s    L_bios            ; yes -- do the long stuff
  222. L_01:
  223.     cmp.w    #8,d0            ; Bcostat?
  224.     bne.s    L_02
  225.     move.w    2(a1),-(sp)        ; push device
  226.     jsr    _ubcostat        ; get status
  227.     bra.s    L_1out
  228. L_02:
  229.     cmp.w    #11,d0            ; Kbshift?
  230.     bne.s    L_bios
  231.     move.w    2(a1),-(sp)        ; push arg
  232.     jsr    _kbshift
  233.     bra.s    L_1out
  234.  
  235. L_bios:
  236.     clr.w    -(sp)            ; no frame format needed
  237.     move.l    _curproc,a0
  238.     pea    4(a0)            ; push pointer to syscall context save
  239.     jsr    _build_context
  240.     lea    _bios_tab,a5        ; set syscall_tab
  241.     move.w    _bios_max,d5        ; set syscall_max
  242. ;
  243. ; copy parameters onto process stack. a0 and a1 were set by _build_context
  244. ;
  245.  
  246.     move.l    _curproc,a0
  247.     move.l    (a0),sp            ; this puts us in our private stack
  248.     move.l    24(a1),-(sp)        ; a1 was set by build_context
  249.     move.l    20(a1),-(sp)
  250.     move.l    16(a1),-(sp)
  251.     move.l    12(a1),-(sp)
  252.     move.l    8(a1),-(sp)
  253.     move.l    4(a1),-(sp)
  254.     move.l    (a1),-(sp)
  255.  
  256. _syscall:
  257. ;
  258. ; check here to see if we need to flush the Bconout() buffer
  259. ;
  260.     tst.w    _bconbsiz        ; characters in buffer?
  261.     beq.s    L_noflush        ; no: OK to proceed
  262. ;
  263. ; watch out, this could cause a context switch
  264. ;
  265.     jsr    _bflush            ; flush the buffer
  266.  
  267. L_noflush:
  268. ;
  269. ; figure out which routine to call
  270. ;
  271.     move.w    (sp),d0
  272.     cmp.w    #-1,d0            ; trapping with -1 means return
  273.     bne.s    check_max        ; the corresponding system table
  274.     move.l    a5,d0
  275.     bra.s    out
  276. check_max:
  277.     cmp.w    d5,d0
  278.     bcc    error
  279. %ifdef ONLY030
  280.     move.l    0(a5,d0.w*4),d0
  281. %else
  282.     add.w    d0,d0
  283.     add.w    d0,d0            ; multiply by 4
  284.     move.l    0(a5,d0.w),d0        ; d0 = syscall_tab[d0]
  285. %endif
  286.     beq    error            ; null entry means invalid call
  287.     addq.w    #2,sp            ; pop function number off stack
  288.     move.l    d0,a0
  289.     jsr    (a0)            ; go do the call
  290. out:
  291.     move.l    _curproc,a0
  292.     move.l    d0,P_SYSCTXT+C_D0(a0)    ; set d0 in the saved context
  293.     move.w    P_SYSCTXT+C_SR(a0),d0    ; get saved status register
  294.     
  295.     tst.l    P_PTRACER(a0)        ; check curproc->ptracer, if not set
  296.     beq.s    notrace            ; then no pending trace; this ensures
  297.     move.w    d0,d1            ; we work with non-MiNT debuggers
  298.     and.w    #$c000,d1        ; are either of the trace bits set
  299.     sne    P_SYSCTXT+C_PTRACE(a0)    ; mark as trace pending/not
  300. notrace:
  301.     tst.w    _proc_clock        ; has process exceeded time slice?
  302.     bne.s    nosleep            ; no -- continue
  303.     btst    #13,d0            ; caller in supervisor mode?
  304.     bne.s    nosleep            ; yes -- don't interrupt
  305.     tst.w    ($43e).w        ; test floppy disk lock variable
  306.     bne.s    nosleep            ; if locked, can't switch
  307. sleep:
  308.     tst.l    _unwound_stack        ; did we unwind sysstack?
  309.     beq.s    noreload1
  310.     move.l    _curproc,a0        ; then reload it before
  311.     move.l    (a0),sp            ; doing anything further
  312. noreload1:
  313.     jsr    _preempt        ; does a sleep(READY_Q)
  314. nosleep:
  315.     ori.w    #$0700,sr        ; spl7()
  316.     jsr    _leave_kernel        ; restore vectors
  317.     move.l    _curproc,a0
  318.     pea    4(a0)
  319.     jsr    _restore_context    ; never returns
  320.  
  321. ;
  322. ; we handle errors by calling through to GEMDOS or the BIOS/XBIOS,
  323. ; as appropriate, and letting them handle it -- that way, if the underlying
  324. ; system has functions we don't know about, they still work
  325. ; to figure out which trap we have to call, we use the system call
  326. ; table placed in a5 earlier
  327.  
  328. error:
  329.     cmp.l    #_xbios_tab,a5
  330.     bne.s    maybe_bios
  331.     trap    #14
  332.     bra    out
  333. maybe_bios:
  334.     cmp.l    #_dos_tab,a5
  335.     beq.s    trap_1
  336.     trap    #13
  337.     bra    out
  338. trap_1:
  339.     trap    #1
  340.     bra    out
  341.  
  342. ;
  343. ; sig_return: user signal handlers return to us. At that point, the
  344. ; stack looks like this:
  345. ;  -4(sp)      (long) sfmt
  346. ;    (sp)      (long) signal number -- was a parameter for user routine
  347. ;
  348.     XDEF    _sig_return
  349.  
  350. _sig_return:
  351.     addq.w    #8,sp            ; pop signal number and sfmt
  352.     move.w    #$11a,-(sp)        ; Psigreturn() system call
  353.     trap    #1
  354. _pc_valid_return:
  355. ; we had better not come back; if we did, something terrible
  356. ; happened, and we might as well terminate
  357.     move.w    #-998,-(sp)
  358.     move.w    #$4c,-(sp)        ; Pterm()
  359.     trap    #1
  360. ;
  361. ; bconout special code: on entry, a1 points to the stack the user
  362. ; was using. If possible, we just buffer the output until later.
  363. ;
  364.  
  365. do_bconout:
  366.     tst.w    _bconbdev        ; is BIOS buffering on?
  367.     bmi    L_bios            ; no buffering -- skip this code
  368.     move.w    2(a1),d0        ; what device is this for?
  369.     beq    L_bios            ; don't buffer the printer
  370.     cmp.w    _bconbdev,d0        ; same device as is buffered?
  371.     bne.s    new_dev            ; no -- maybe we can't do this
  372. put_buf:
  373.     move.w    4(a1),d0        ; get the character to output
  374.     move.w    _bconbsiz,d1        ; get index into buffer table
  375.     cmp.w    #255,d1            ; buffer full?
  376.     beq    L_bios            ; yes -- flush it out
  377.     lea    _bconbuf,a0
  378.     add.w    d1,a0
  379.     move.b    d0,(a0)            ; store the character
  380.     addq.w    #1,d1
  381.     move.w    d1,_bconbsiz
  382.     ori.w    #$0700,sr        ; spl7()
  383.     jsr    _leave_kernel        ; restore vectors
  384.     moveq.l    #-1,d0            ; return character output OK
  385.     rte
  386.  
  387. new_dev:
  388.     tst.w    _bconbsiz        ; characters already in buffer?
  389.     bne    L_bios            ; yes: we can't buffer this one
  390.     move.w    d0,_bconbdev        ; no: OK, we have a new device
  391.     bra.s    put_buf
  392.  
  393. ;
  394. ; _lineA0: MiNT calls this to get the address of the line A variables
  395. ;
  396.     XDEF    _lineA0
  397. _lineA0:
  398.     movem.l    d2/a2,-(sp)    ; save scratch registers
  399.     dc.w    $a000        ; call the line A initialization routine
  400.     movem.l    (sp)+,d2/a2
  401.     rts
  402.  
  403. ;
  404. ; _call_aes: calls the GEM AES, using the control block passed as
  405. ;            a parameter. Used only for doing appl_init(), to see
  406. ;         if the AES is active yet
  407. ;
  408.     XDEF    _call_aes
  409. _call_aes:
  410.     move.l    4(sp),d1    ; fetch pointer to parameter block
  411.     move.w    #$c8,d0        ; magic number for AES
  412.     movem.l    d2/a2,-(sp)    ; save scratch registers
  413.     trap    #2
  414.     movem.l    (sp)+,d2/a2
  415.     rts
  416. ;
  417. ; _call_dosound:
  418. ;
  419.     XDEF    _call_dosound
  420. _call_dosound:
  421.     move.l    4(sp),-(sp)
  422.     move.w    #32,-(sp)
  423.     trap    #14
  424.     addq.w    #6,sp
  425.     rts
  426.  
  427. ;
  428. ; _callout: Call an external function, passing <32 bytes of arguments,
  429. ; and return the value from the function. NOTE: we must be careful
  430. ; to save all registers here!
  431. ;
  432.     XDEF    _callout
  433.     XDEF    _callout1
  434.     XDEF    _callout2
  435.     XDEF    _callout6
  436.     XDEF    _callout6spl7
  437. ;
  438. ; _callout is the general purpose one
  439. ;
  440. _callout:
  441.     lea    8(sp),a0        ; pointer to args
  442.     move.l    4(sp),a1        ; pointer to pointer to function
  443.     movem.l    d2-d7/a2-a6,-(sp)    ; save registers
  444.     movem.l    (a0),d0-d7        ; copy parameters
  445.     movem.l    d0-d7,-(sp)
  446.     suba.l    a5,a5            ; the BIOS expects 0 in a5
  447.     jsr    (a1)            ; go do it
  448.     lea    32(sp),sp
  449.     movem.l    (sp)+,d2-d7/a2-a6    ; restore reggies
  450.     rts
  451. ;
  452. ; _callout2 and _callout1 are for functions with just 1 or
  453. ; 2 16 bit parameters. We cheat and use the same code for
  454. ; both, since passing 32 bits isn't much more expensive than
  455. ; passing 16 bits (and since the called function will just
  456. ; ignore any extra arg)
  457. ;
  458.  
  459. _callout1:
  460. _callout2:
  461.     movem.l    4(sp),a0/a1        ; get function ptr & args
  462.     movem.l    d2-d7/a2-a6,-(sp)    ; save reggies
  463.     move.l    a1,-(sp)        ; push args
  464.     suba.l    a5,a5            ; the BIOS expects 0 in a5
  465.     jsr    (a0)            ; do function
  466.     addq.w    #4,sp
  467.     movem.l    (sp)+,d2-d7/a2-a6    ; restore reggies
  468.     rts
  469. ;
  470. ; _callout6 passes 6 words, saving sr
  471. ;
  472. _callout6:
  473.     movem.l    d2-d7/a2-a6,-(sp)    ; save registers
  474.     movem.l    4+44(sp),a0-a3        ; get function ptr & args
  475.     move.w    sr,-(sp)
  476.     movem.l    a1-a3,-(sp)        ; copy args
  477.     suba.l    a5,a5            ; the BIOS expects 0 in a5
  478.     jsr    (a0)            ; go do it
  479.     lea    12(sp),sp
  480.     move.w    (sp)+,sr
  481.     movem.l    (sp)+,d2-d7/a2-a6    ; restore reggies
  482.     rts
  483. ;
  484. ; _callout6spl7 passes 6 words at ipl7
  485. ;
  486. _callout6spl7:
  487.     movem.l    d2-d7/a2-a6,-(sp)    ; save registers
  488.     movem.l    4+44(sp),a0-a3        ; get function ptr & args
  489.     move.w    sr,-(sp)
  490.     movem.l    a1-a3,-(sp)        ; copy args
  491.     suba.l    a5,a5            ; the BIOS expects 0 in a5
  492.     ori.w    #$0700,sr        ; spl7()
  493.     jsr    (a0)            ; go do it
  494.     lea    12(sp),sp
  495.     move.w    (sp)+,sr
  496.     movem.l    (sp)+,d2-d7/a2-a6    ; restore reggies
  497.     rts
  498.  
  499. ;
  500. ; do_usrcall: call the user supplied function (*usrcall)(), with
  501. ; arguments given in the longwords usrarg1..usrarg5. Return value
  502. ; is placed in usrret. This function is used by the Supexec code
  503. ; in xbios.c.
  504.  
  505.     XDEF    _do_usrcall
  506.     XREF    _usrret
  507.     XREF    _usrcall
  508.     XREF    _usrarg1,_usrarg2,_usrarg3,_usrarg4,_usrarg5
  509.  
  510. _do_usrcall:
  511.     move.l    _usrarg5,-(sp)
  512.     move.l    _usrarg4,-(sp)
  513.     move.l    _usrarg3,-(sp)
  514.     move.l    _usrarg2,-(sp)
  515.     move.l    _usrarg1,-(sp)
  516.     move.l    _usrcall,-(sp)    ; the user expects to see this on the stack
  517.     pea    ucret(pc)    ; so rts puts us back here
  518.     move.l    _usrcall,-(sp)    ; this copy is for us to use
  519.     rts            ; to jump to (we don't want to use registers)
  520. ucret:
  521.     lea    24(sp),sp    ; fix up stack
  522.     move.l    d0,_usrret    ; save returned value
  523.     rts            ; back to caller
  524.  
  525.     END
  526.